/**
 * // 转换前：
source = [{
            id: 1,
            pid: 0,
            name: 'body'
          }, {
            id: 2,
            pid: 1,
            name: 'title'
          }, {
            id: 3,
            pid: 2,
            name: 'div'
          }]
// 转换为: 
tree = [{
          id: 1,
          pid: 0,
          name: 'body',
          children: [{
            id: 2,
            pid: 1,
            name: 'title',
            children: [{
              id: 3,
              pid: 1,
              name: 'div'
            }]
          }
        }]
 * 
 * **/

const source = [{
  id: 1,
  pid: 0,
  name: 'body'
}, {
  id: 2,
  pid: 1,
  name: 'title'
}, {
  id: 3,
  pid: 2,
  name: 'div'
}];

// 方法1： 递归
function list2tree1(source) {
  const target = [];
  for (const node of source) {
    // 如果pid === 0 就表示是根节点
    if (node.pid === 0) {
      let p = {...node};
      // 对于根节点来说要增加一个child属性来存子节点的信息
      p.child = getChildren(p.id, source);
      target.push(p);
    };
  };

  return target;
};

function getChildren(id, source) {  // 传入父节点的id
  const children = [];
  // 找到pid === id的节点
  for (const node of source) {
    if (node.pid === id) {
      children.push(node);
    }
  };

  // 这里的作用就是可能存在不是根节点但是也有子节点的节点 所以这里要进行遍历
  for (const node of children) {
    const children = getChildren(node.id, source);
    if (children.length) {
      node.children = children;
    };
  };

  return children;
};


// console.log(list2tree1(source));


// 方法2：两次循环
function list2tree2(source) {
  source.forEach(child => {
    const pid = child.pid;
    if (pid) {   // pid !== 0 的说明不是根节点
      source.forEach(parent => {
        if (parent.id === pid) {
          parent.children = parent.children || [];
          parent.children.push(child);
        };
      });
    };
  });

  return source.filter(item => !item.pid);
};

// console.log(list2tree2(source));

// 方法3：使用map
function list2tree3(source) {
  const [map, target] = [{}, []];

  for (let i = 0; i < source.length; i++) {
    map[source[i].id] = i;
    source[i].children = [];
  };

  for (let i = 0; i < source.length; i++) {
    const node = source[i];
    if (node.pid && source[map[node.pid]]) {
      source[map[node.pid]].children.push(node)
    } else {
      target.push(node);
    };
  };

  return target;
};


// console.log(list2tree3(source));


